import React, { FC, useEffect, useState } from 'react'
import styles from './Image2ImageMethod.module.scss'
import { useColorVar, useStyles } from '@/hooks/styles'
import { MethodCard } from '@/components/graph/methods/MethodCard/MethodCard'
import { SvgIcon } from '@/components/icons'
import { DataAnalysis } from '@/components/icons/DataAnalysis'
import { Graph, Node } from '@antv/x6'
import { TextAsset } from '@/components/graph/assets/TextAsset/TextAsset'
import { observer } from 'mobx-react'
import { AssetInPort } from '@/components/graph/assets/AssetInPort/AssetInPort'
import {
  IImage2ImageCardContext,
  ITextAssetCardContext,
  UUID,
} from '@/store/metaStore'
import { useMetaStore, useWtsStore } from '@/hooks'

// TODO: move it above
interface IParam {
  title: string
  type: 'radio' | 'slider' | 'input'
}
interface IContinousParam extends IParam {
  type: 'slider'
  default: number
  min: number
  max: number
}
interface IDiscreteParam<T extends number | string> extends IParam {
  type: 'radio'
  default: T
  options: T[]
}
interface IInputParam<T extends number | string> extends IParam {
  type: 'input'
  default: T
}
// TODO: use i18n
const modelParam: IDiscreteParam<string> = {
  type: 'radio',
  title: '图像生成模型',
  default: 'stablediffuusion_v1_5',
  options: ['stablediffuusion_v1_5'],
}
const generateNumParam: IContinousParam = {
  type: 'slider',
  title: '生成数量',
  default: 1,
  min: 1,
  max: 4,
}
const seedParam: IInputParam<number> = {
  type: 'input',
  title: '随机种子数值',
  default: -1,
}
const relatedScoreParam: IContinousParam = {
  type: 'slider',
  title: '与提示词相关程度',
  default: 1,
  min: 1,
  max: 16,
}
const referenceStrengthParam: IContinousParam = {
  type: 'slider',
  title: '参考图强度',
  default: 0.6,
  min: 0,
  max: 1,
}
const i2iParms = [
  modelParam,
  generateNumParam,
  seedParam,
  relatedScoreParam,
  referenceStrengthParam,
]

interface IImage2ImageMethodParams {
  data1?: any
  node?: Node
  graph?: Graph
  cardID?: UUID
  cardIndex?: number
  inputPositivePromptAssetCardID?: UUID
  inputNegativePromptAssetCardID?: UUID
  inputReferenceImageAssetCardID?: UUID
  inputMaskImageAssetCardID?: UUID
}
export const Image2ImageMethod: FC<IImage2ImageMethodParams> = observer(
  ({
    node,
    graph,
    cardID,
    cardIndex,
    inputPositivePromptAssetCardID,
    inputNegativePromptAssetCardID,
    inputReferenceImageAssetCardID,
    inputMaskImageAssetCardID,
  }) => {
    const c = useColorVar()
    const styleClass = useStyles(styles)
    const metaStore = useMetaStore()
    const wtsStore = useWtsStore()

    useEffect(() => {
      const {
        inputPositivePromptAssetCardID,
        inputReferenceImageAssetCardID,
        inputNegativePromptAssetCardID,
        inputMaskImageAssetCardID,
      } = metaStore.cardContextArray[cardIndex] as IImage2ImageCardContext
      if (inputPositivePromptAssetCardID) {
        setInputPort1CardUUID(inputPositivePromptAssetCardID)
      }
      if (inputNegativePromptAssetCardID) {
        setInputPort2CardUUID(inputNegativePromptAssetCardID)
      }
      if (inputReferenceImageAssetCardID) {
        setInputPort3CardUUID(inputReferenceImageAssetCardID)
      }
      if (inputMaskImageAssetCardID) {
        setInputPort4CardUUID(inputMaskImageAssetCardID)
      }
    }, [metaStore.cardContextArray[cardIndex]]) // TODO

    const [inputPort1CardUUID, setInputPort1CardUUID] = useState<UUID>(
      inputPositivePromptAssetCardID
    )
    const [inputPort2CardUUID, setInputPort2CardUUID] = useState<UUID>(
      inputNegativePromptAssetCardID
    )
    const [inputPort3CardUUID, setInputPort3CardUUID] = useState<UUID>(
      inputReferenceImageAssetCardID
    )
    const [inputPort4CardUUID, setInputPort4CardUUID] = useState<UUID>(
      inputMaskImageAssetCardID
    )

    const isGenerateButtonFrozen = () =>
      !inputPort1CardUUID &&
      !inputPort2CardUUID &&
      !inputPort3CardUUID &&
      !inputPort4CardUUID // TODO

    const [outputImageURL, setOutputImageURL] = useState<string>('')

    const image2imageGenerate = async () => {
      const designMethod = await wtsStore.operator.get_method_data(cardID)
      console.log('image2imageGenerate, inPorts', designMethod.inPorts)
      const inPort = designMethod.inPorts[0]
      try {
        inPort.assets = [
          (metaStore.cardContext[inputPort1CardUUID] as ITextAssetCardContext)
            ?.assetID,
          (metaStore.cardContext[inputPort2CardUUID] as ITextAssetCardContext)
            ?.assetID,
          (metaStore.cardContext[inputPort3CardUUID] as ITextAssetCardContext)
            ?.assetID,
          (metaStore.cardContext[inputPort4CardUUID] as ITextAssetCardContext)
            ?.assetID,
        ]
        console.log('image2imageGenerate, inports assets', inPort.assets)
      } catch {
        console.error('image2imageGenerate, inPort not asset')
      }
      await wtsStore.operator.update_method({
        ...designMethod,
        inPorts: [inPort],
      })
      console.log('image2imageGenerate before run method')
      let retDesignMethod
      try {
        retDesignMethod = await wtsStore.operator.run_method(designMethod.id)
      } catch (e) {
        console.error('image2imageGenerate run method exception', e)
      }
      console.log('image2imageGenerate return', retDesignMethod)
      // setOutputImageURL(
      //   await Promise.all(
      //     retDesignMethod.outputs[0]?.goals?.map(
      //       async ({ id }) => await get_asset_data(id)
      //     )
      //   )
      // )
      console.log('summarize return', retDesignMethod)
    }

    const input = (
      <>
        <AssetInPort assetType={'string'} />
        <AssetInPort assetType={'string'} />
        <AssetInPort assetType={'img'} />
        <AssetInPort assetType={'img'} />
      </>
    )

    const output = (
      <TextAsset width={'100%'} text={outputImageURL} isEditable={false} />
    )

    // TODO: replace icon
    return (
      <MethodCard
        width={384}
        cardTitle={'I2I图片生成'}
        cardIcon={<SvgIcon icon={DataAnalysis} />}
        node={node}
        graph={graph}
        input={input}
        output={output}
        isButtonDisabled={isGenerateButtonFrozen()}
        onClick={image2imageGenerate}
      ></MethodCard>
    )
  }
)
